// #接口的合并
// 接口还能够使用继承进行合并，在继承时子接口可以声明同名属性，但并不能覆盖掉父接口中的此属性。子接口中的属性类型需要能够兼容（extends）父接口中的属性类型：

interface Struct1 {
  primitiveProp: string;
  objectProp: {
    name: string;
  }

  unionProp: string | number;
}
// 接口“Struct2”错误扩展接口“Struct1”。
interface Struct2 extends Struct1 {
  //  // “primitiveProp”的类型不兼容。不能将类型“number”分配给类型“string”。
  // primitiveProp: number;
  //   // 属性“objectProp”的类型不兼容。
  // objectProp: {
  //   age: number;
  // };
  // // 属性“unionProp”的类型不兼容。不能将类型“boolean”分配给类型“string | number”。
  // unionProp: boolean;
}

//类似的，如果你直接声明多个同名接口，虽然接口会进行合并，但这些同名属性的类型仍然需要兼容，此时的表现其实和显式扩展接口基本一致：
interface Struct3 {
  primitiveProp?: string;
}

interface Struct3 {
  lys?: number;
}

let obj: Struct3 = {
  lys: 1,
  primitiveProp: 'lys'
}
// 这也是接口和类型别名的重要差异之一。


// 那么接口和类型别名之间的合并呢？其实规则一致，如接口继承类型别名，和类型别名使用交叉类型合并接口：
type Base = {
  name: string;
}
interface IDerived extends Base {
  // // 报错！就像继承接口一样需要类型兼容
  // name: number;
  age: number;
}

let obj2: IDerived = {
  age: 18,
  name: 'lys'
}

interface IBase {
  name: string;
}

type Derived = IBase & {
  name: number;
}
type Derived2 = IBase & IDerived

let obj3: Derived2 = {
  name: "lsy",
  age: 12
}

// 更强大的可辨识联合类型分析
// 在 4.5、4.6、4.7 版本中都有或多或少的场景增强。而这里说的增强，其实就包括了对可辨识联合类型的分析能力。比如下面这个例子在此前（4.6 版本以前）的 TypeScript 代码中会报错：
type Args = ["a", number] | ['b', string]

type Func = (...args: ['a', number] | ['b', string]) => void;

const f1: Func = (kind, payload) => {
  if (kind === 'a') {
    //     // 仍然是 string | number
    payload.toFixed();
  }
  if (kind === 'b') {
    payload.toUpperCase();
  }
}


